<?php

class BcLibAssignmentOperators implements CliLibrary
{
	private static $operators = array(
		ExpOperator::TYPE_PREFIX => array(
			'++' => array(PREC_PREFIX, 'op_preinc', '++p'),
			'--' => array(PREC_PREFIX, 'op_predec', '--p'),
		),
		ExpOperator::TYPE_POSTFIX => array(
			'++'=> array(PREC_POSTFIX, 'op_postinc'),
			'--' => array(PREC_POSTFIX, 'op_postdec'),
		),
		ExpOperator::TYPE_RIGHT => array(
			'+=' => array(PREC_ASSIGNMENT, 'op_assign_addition'),
			'-=' => array(PREC_ASSIGNMENT, 'op_assign_substraction'),
			'/=' => array(PREC_ASSIGNMENT, 'op_assign_division'),
			'*=' => array(PREC_ASSIGNMENT, 'op_assign_multiplication'),
			'^=' => array(PREC_ASSIGNMENT, 'op_assign_power'),
			'&=' => array(PREC_ASSIGNMENT, 'op_assign_bitand'),
			'|=' => array(PREC_ASSIGNMENT, 'op_assign_bitor'),
		)
	);

	public static function addLibrary (CliMode $mode)
	{
		$mode->addOperators(__CLASS__, self::$operators);
	}

	public static function op_postinc (ArgContext $args)
	{
		$args->operandCount(1);
		$args->requireType(0, 'variable');
		$value = $args->toNumber(0);
		$args[0]->set($value + 1, $args->getContext());
		return $value;
	}

	public static function op_postdec (ArgContext $args)
	{
		$args->operandCount(1);
		$args->requireType(0, 'variable');
		$value = $args->toNumber(0);
		$args[0]->set($value - 1, $args->getContext());
		return $value;
	}

	public static function op_preinc (ArgContext $args)
	{
		$args->operandCount(1);
		$args->requireType(0, 'variable');
		$value = $args->toNumber(0) + 1;
		$args[0]->set($value, $args->getContext());
		return $value;
	}

	public static function op_predec (ArgContext $args)
	{
		$args->operandCount(1);
		$args->requireType(0, 'variable');
		$value = $args->toNumber(0) - 1;
		$args[0]->set($value, $args->getContext());
		return $value;
	}

	public static function op_assign_addition (ArgContext $args)
	{
		return self::assigment($args, 'addition');
	}

	public static function op_assign_substraction (ArgContext $args)
	{
		return self::assigment($args, 'substraction');
	}

	public static function op_assign_multiplication (ArgContext $args)
	{
		return self::assigment($args, 'multiplication');
	}

	public static function op_assign_division (ArgContext $args)
	{
		return self::assigment($args, 'division');
	}

	public static function op_assign_power (ArgContext $args)
	{
		return self::assigment($args, 'power');
	}

	public static function op_assign_bitand (ArgContext $args)
	{
		return self::assigment($args, 'bitand');
	}

	public static function op_assign_bitor (ArgContext $args)
	{
		return self::assigment($args, 'bitor');
	}

	private static function assigment (ArgContext $args, $type)
	{
		$args->operandCount(2);
		$args->requireTypes('variable', 'value');
		$a = $args->toNumber(0);
		$b = $args->toNumber(1);

		switch ($type)
		{
			case 'addition': $value = $a + $b; break;
			case 'substraction': $value = $a - $b; break;
			case 'multiplication': $value = $a * $b; break;
			case 'division': $value = $a / $b; break;
			case 'power' : $value = pow($a, $b); break;
			case 'bitand' : $value = $a & $b; break;
			case 'bitor' : $value = $a | $b; break;
		}

		$args[0]->set($value, $args->getContext());
		return $value;
	}
}